package com.ygqh.baby.handler;

import com.alibaba.fastjson.JSON;
import com.ygqh.baby.ao.*;
import com.ygqh.baby.excel.ExcelHandler;
import com.ygqh.baby.excel.domain.OutOrderImportEntity;
import com.ygqh.baby.model.PromotionBo;
import com.ygqh.baby.model.SaveOutOrderImportParam;
import com.ygqh.baby.model.SkuBasicData;
import com.ygqh.baby.po.YgOrder;
import com.ygqh.baby.po.YgOrderDetail;
import com.ygqh.baby.po.YgStock;
import com.ygqh.baby.service.YgFrameCodeService;
import com.ygqh.baby.service.YgOrderService;
import com.ygqh.baby.service.YgSkuService;
import com.ygqh.baby.service.YgStockService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 〈订单导入处理器〉
 *
 * @author guohao
 * @date 2019/5/14 9:19
 * @since 1.0.0
 */
@Component
public class OutOrderImportHandler {

    @Autowired
    private YgSkuService ygSkuService;
    @Autowired
    private YgFrameCodeService ygFrameCodeService;
    @Autowired
    private YgOrderService ygOrderService;
    @Autowired
    private YgStockService ygStockService;

    public List<OutOrderImportEntity> loadOrderExcel(MultipartFile uploadFile) {
        List<OutOrderImportEntity> orderImportEntities = ExcelHandler.loadExcel(uploadFile, OutOrderImportEntity.class);
        checkOrder(orderImportEntities);
        return orderImportEntities;
    }

    @Transactional(rollbackFor = Exception.class)
    public Message saveOutOrder(SaveOutOrderImportParam saveOutOrderImportParam) {
        List<YgOrder> orderList = buildOrder(saveOutOrderImportParam);
        int i = ygOrderService.saveOrderList(orderList);
        reduceStock(orderList);
        return Message.success(i);
    }

    private void reduceStock(List<YgOrder> orderList) {
        List<YgOrderDetail> detailList = orderList.stream().flatMap(order -> order.getOrderDetail().stream()).collect(Collectors.toList());

        Map<String, List<YgOrderDetail>> listMap = detailList.stream().collect(Collectors.groupingBy(YgOrderDetail::getSkuCode));
        List<YgStock> stockList = new ArrayList<>(listMap.size());
        listMap.forEach((key, value) -> {
            YgStock stock = new YgStock();
            Long quantity = value.stream().map(YgOrderDetail::getQuantity).reduce(0L, (a, b) -> a + b);
            stock.setSkuCode(key);
            stock.setAmount(quantity);
            stockList.add(stock);
        });
        ygStockService.reduceStock(stockList, "saveOutOrder");

    }

    private List<YgOrder> buildOrder(SaveOutOrderImportParam saveOutOrderImportParam) {
        Long userId = 46L;
        Date currentDate = new Date();
        String platformNo = saveOutOrderImportParam.getPlatformNo();
        String platformName = saveOutOrderImportParam.getPlatformName();

        Map<String, List<OutOrderImportEntity>> orderMap = saveOutOrderImportParam.getDetailList().stream()
                .collect(Collectors.groupingBy(OutOrderImportEntity::getOutCode));
        List<YgOrder> orderList = new ArrayList<>();
        orderMap.forEach((key, vlue) -> {
            YgOrder order = doBuildOrder(platformNo, platformName, vlue, currentDate, userId);
            orderList.add(order);
        });

        return orderList;
    }

    private YgOrder doBuildOrder(String paltformNo, String platformName, List<OutOrderImportEntity> vlue, Date currentDate, Long userId) {
        Long orderId = ygFrameCodeService.getFrameCode(CodeType.Order, currentDate);
        String outCode = vlue.get(0).getOutCode();
        BigDecimal productPrice = vlue.stream().map(item -> item.getSalePrice().multiply(new BigDecimal(item.getQuantity()))).reduce(BigDecimal.ZERO, BigDecimal::add);
        YgOrder order = new YgOrder();
        order.setSourceCode(outCode);
        order.setOrderId(orderId);
        order.setUserId(userId);
        order.setSupplierId(vlue.get(0).getSkuBasicData().getSupplierId());
        order.setParentId(orderId);
        order.setProductPrice(productPrice);
        order.setTotalPrice(productPrice);
        order.setPaidPrice(productPrice);
        order.setManjianPrice(BigDecimal.ZERO);
        order.setYouhuijuanPrice(BigDecimal.ZERO);
        order.setNewCustomDisPrice(BigDecimal.ZERO);
        order.setBmdisPrice(BigDecimal.ZERO);
        order.setGroupDisPrice(BigDecimal.ZERO);
        order.setVipDisPrice(BigDecimal.ZERO);
        order.setAccountPrice(BigDecimal.ZERO);
        order.setExpressPrice(BigDecimal.ZERO);
        order.setPackDisPrice(BigDecimal.ZERO);

        order.setCreateTime(currentDate);
        order.setPaidTime(currentDate);
        order.setOrderStatus(OrderStatus.WaitingSend);
        order.setAppType(AppType.WeChat);
        order.setPayType(PayType.WeChat);
        order.setOrderType(OrderType.Ordinary);
        order.setPlatformNo(paltformNo);
        order.setPlatformName(platformName);

        order.setReceiver(vlue.get(0).getReceiver());
        order.setProvinceName(vlue.get(0).getProvinceName());
        order.setCityName(vlue.get(0).getCityName());
        order.setAreaName(vlue.get(0).getAreaName());
        order.setAddress(vlue.get(0).getAddress());
        order.setTelPhone(vlue.get(0).getTelPhone());
        order.setStatus(DataStatus.Valid);
        order.setCommentStatus(CommentStatus.UnComplete);

        List<YgOrderDetail> orderDetailList = new ArrayList<>(vlue.size());
        for (OutOrderImportEntity detail : vlue) {
            SkuBasicData skuBasicData = detail.getSkuBasicData();
            YgOrderDetail orderDetail = new YgOrderDetail();
            orderDetail.setOrderId(orderId);
            orderDetail.setSkuId(skuBasicData.getSkuId());
            orderDetail.setSkuCode(skuBasicData.getSkuCode());
            orderDetail.setSupplierId(skuBasicData.getSupplierId());
            orderDetail.setProductId(skuBasicData.getProductId());
            orderDetail.setProductCode(skuBasicData.getProductCode());
            orderDetail.setProductName(skuBasicData.getProductName());
            orderDetail.setShortName(skuBasicData.getColor());
            orderDetail.setSalePrice(detail.getSalePrice());
            orderDetail.setImageUrl(skuBasicData.getMainImageUrl());
            orderDetail.setUnitName(skuBasicData.getUnitName());
            orderDetail.setSize(skuBasicData.getSizeName());
            orderDetail.setPromotionType(PromotionType.Ordinary);
            orderDetail.setDetailStatus(OrderDetailStatus.WaitingSend);
            orderDetail.setRefundStatus(RefundStatus.NoRefund);
            orderDetail.setCostPrice(skuBasicData.getCostPrice());
            orderDetail.setRealPrice(detail.getSalePrice().multiply(new BigDecimal(detail.getQuantity())));
            orderDetail.setQuantity(detail.getQuantity());


            orderDetail.setYhqDisPrice(BigDecimal.ZERO);
            orderDetail.setMjDisPrice(BigDecimal.ZERO);
            orderDetail.setBmDisPrice(BigDecimal.ZERO);
            orderDetail.setNewCustomDisPrice(BigDecimal.ZERO);
            orderDetail.setPackDisPrice(BigDecimal.ZERO);
            orderDetail.setVipDisPrice(BigDecimal.ZERO);
            orderDetail.setAccountPrice(BigDecimal.ZERO);
            orderDetail.setExpressPrice(BigDecimal.ZERO);
            orderDetail.setShareRate(BigDecimal.ZERO);
            orderDetail.setForeverRate(BigDecimal.ZERO);

            PromotionBo promotionBo = new PromotionBo();
            promotionBo.setType(PromotionType.Ordinary);
            orderDetail.setPromotionRemark(JSON.toJSONString(promotionBo));

            orderDetailList.add(orderDetail);
        }
        order.setOrderDetail(orderDetailList);
        return order;
    }

    private void checkOrder(List<OutOrderImportEntity> list) {
        String[] skuCodes = list.stream().map(OutOrderImportEntity::getSkuCode).toArray(String[]::new);
        List<SkuBasicData> skuBasicDataList = ygSkuService.getBasicDataBySkuCode(PromotionType.Ordinary, skuCodes);
        Map<String, List<SkuBasicData>> listMap = skuBasicDataList.stream().collect(Collectors.groupingBy(SkuBasicData::getSkuCode));
        list.forEach(outOrderImportEntity -> doCheck(outOrderImportEntity, listMap));
    }

    private void doCheck(OutOrderImportEntity outOrderImportEntity, Map<String, List<SkuBasicData>> listMap) {
        if (!listMap.containsKey(outOrderImportEntity.getSkuCode())) {
            outOrderImportEntity.setErrorMsg(outOrderImportEntity.getErrorMsg() + " 系统中不存在该商品，skuCode：" + outOrderImportEntity.getSkuCode());
        } else {
            boolean existed = ygOrderService.existedByOutCode(outOrderImportEntity.getOutCode());
            if (existed) {
                outOrderImportEntity.setErrorMsg(outOrderImportEntity.getErrorMsg() + " 外部单号已存在。");
            } else {
                outOrderImportEntity.setSkuBasicData(listMap.get(outOrderImportEntity.getSkuCode()).get(0));
            }
        }

    }

}
